package com.gemini.main.nio;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

/**
 * 异步io
 */
public class AsynchronousIoSample {

    public static void main(String[] args) throws IOException {
        AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress("192.168.1.55", 8080));

        // 自己定义一个 Attachment 类，用于传递一些信息
        Attachment attachment = new Attachment();
        attachment.setServer(server);

        server.accept(attachment, new CompletionHandler<AsynchronousSocketChannel, Attachment>() {
            @Override
            public void completed(AsynchronousSocketChannel result, Attachment attachment) {
                try {

                    SocketAddress clientAddress = result.getRemoteAddress();
                    System.out.println("收到新的连接：" + clientAddress);

                    // 收到新的连接后，server 应该重新调用 accept 方法等待新的连接进来
                    server.accept(attachment, this);

                    Attachment newAtt = new Attachment();
                    newAtt.setServer(server);
                    newAtt.setClient(result);
                    newAtt.setReadMode(true);
                    newAtt.setBuffer(ByteBuffer.allocate(2048));

                    // 这里也可以继续使用匿名实现类，不过代码不好看，所以这里专门定义一个类
                    result.read(newAtt.getBuffer(), newAtt, new com.gemini.main.nio.ChannelHandler());
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

            @Override
            public void failed(Throwable exc, Attachment attachment) {
                System.out.println("accept failed");
            }
        });

        // 为了防止 main 线程退出
        try {
            Thread.currentThread().join();
        } catch (InterruptedException e) {
        }

    }

    public static class Attachment {
        private AsynchronousServerSocketChannel server;

        private AsynchronousSocketChannel client;

        private boolean readMode;

        private ByteBuffer buffer;

        public void setServer(AsynchronousServerSocketChannel server) {
            this.server = server;
        }

        public AsynchronousServerSocketChannel getServer() {
            return server;
        }

        public AsynchronousSocketChannel getClient() {
            return client;
        }

        public void setClient(AsynchronousSocketChannel client) {
            this.client = client;
        }

        public boolean isReadMode() {
            return readMode;
        }

        public void setReadMode(boolean readMode) {
            this.readMode = readMode;
        }

        public ByteBuffer getBuffer() {
            return buffer;
        }

        public void setBuffer(ByteBuffer buffer) {
            this.buffer = buffer;
        }
    }
}
